﻿/*
 * 原始代码从 http://www.jeremyskinner.co.uk/2011/01/24/strongly-typed-data-access-with-webmatrix-data/ 拷贝
 * 
 * 日期：2011-7-14
 * 作者：minco
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WebMatrix.Data;
using System.Data.Common;
using System.Data;
using System.Reflection;
using System.Globalization;

namespace WebMatrix.Data
{
    public static class DataExtensions
    {
        /// <summary>
        /// 返回强类型T的枚举集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <param name="commandText"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static IEnumerable<T> Query<T>(this Database db, string commandText, params object[] args)
        {

            var queryResults = db.Query(commandText, args==null||args.Length==0?null:args);
            if (queryResults != null)
            {
                var mapper = Mapper<T>.Create();
                foreach (var record in queryResults)
                {
                    yield return mapper.Map(record);
                }
            }

            yield break;
        }

        /// <summary>
        /// 返回强类型T的一个实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="db"></param>
        /// <param name="commandText"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static T QuerySingle<T>(this Database db, string commandText, params object[] args)
        {
            var queryResult = db.QuerySingle(commandText, args == null || args.Length == 0 ? null : args);
            if (queryResult != null)
            {
                var mapper = Mapper<T>.Create();
                return mapper.Map(queryResult);
            }

            return default(T);
        }

        /// <summary>
        /// 将动态实例转型到具体类的实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        /// <remarks>即与IEnumerable.Cast一致，但使用新名称使得不会出现选择冲突</remarks>
        public static IEnumerable<T> MapTo<T>(this IEnumerable<dynamic> source)
        {
            var mapper = Mapper<T>.Create();
            if (source != null)
            {
                foreach (var record in source)
                {
                    yield return mapper.Map(record);
                }
            }

            yield break;
        }

        //private static void EnsureConnectionOpen(this Database db)
        //{
        //    // If the connection isn't open then open it
        //    if (db.Connection.State != ConnectionState.Open)
        //    {
        //        db.Connection.Open();
        //    }
        //}

        //private static void AddParameters(DbCommand command, object[] args)
        //{
        //    if (args == null)
        //    {
        //        return;
        //    }

        //    // Create numbered parameters
        //    IEnumerable<DbParameter> parameters = args.Select((o, index) =>
        //    {
        //        var parameter = command.CreateParameter();
        //        parameter.ParameterName = index.ToString(CultureInfo.InvariantCulture);
        //        parameter.Value = o;
        //        return parameter;
        //    });

        //    foreach (var p in parameters)
        //    {
        //        command.Parameters.Add(p);
        //    }
        //}

        //private static IEnumerable<string> GetColumns(DbDataRecord record)
        //{
        //    // Get all of the column names for this query
        //    for (int i = 0; i < record.FieldCount; i++)
        //    {
        //        yield return record.GetName(i);
        //    }
        //    yield break;
        //}

        //private static ConstructorInfo s_DynamicRecordCtor = typeof(DynamicRecord).GetConstructor(new Type[] { typeof(IEnumerable<string>), typeof(IDataRecord) });

        //public static IEnumerable<dynamic> Query( this Database db, string commandText, CommandType commandType, params object[] parameters)
        //{
        //    db.EnsureConnectionOpen();

        //    DbCommand command = db.Connection.CreateCommand();
        //    command.CommandText = commandText;

        //    AddParameters(command, parameters);
        //    using (command) {
        //        IEnumerable<string> columnNames = null;
        //        using (DbDataReader reader = command.ExecuteReader()) {
        //            foreach (DbDataRecord record in reader) {
        //                if (columnNames == null) {
        //                    columnNames = GetColumns(record);
        //                }
                        
        //                yield return Activator.CreateInstance(typeof(DynamicRecord), BindingFlags.Instance| BindingFlags.NonPublic,new object[]{columnNames, record},CultureInfo.InvariantCulture);
        //            }
        //        }
        //    }
        //}
    }
}
